package de.fhwf.mixedreality.client;

import de.fhwf.mixedreality.client.IClient;

public abstract class AbstractPositionsStorage implements IPositionsStorage {
	protected Vector mBallPos;
	protected Vector mOpponentPos[];
	protected double mOpponentOrientation[];
	protected Vector mTeammatePos[];
	protected double mTeammateOrientation[];
	protected Vector mMyGoalPole1;
	protected Vector mMyGoalPole2;
	protected Vector mOpGoalPole1;
	protected Vector mOpGoalPole2;
	protected Vector mMyCornerFlag1;
	protected Vector mMyCornerFlag2;
	protected Vector mOpCornerFlag1;
	protected Vector mOpCornerFlag2;
	protected IClient mClient;

	public AbstractPositionsStorage(IClient client) {
		mClient = client;
		mBallPos = new Vector(0, 0);
		mOpponentPos = new Vector[IClient.MAX_PLAYERS];
		mOpponentOrientation = new double[IClient.MAX_PLAYERS];
		mTeammatePos = new Vector[IClient.MAX_PLAYERS];
		mTeammateOrientation = new double[IClient.MAX_PLAYERS];
		for (int i = 0; i < IClient.MAX_PLAYERS; i++) {
			mOpponentPos[i] = new Vector(0, 0);
			mOpponentOrientation[i] = 0.0;
			mTeammatePos[i] = new Vector(0, 0);
			mTeammateOrientation[i] = 0.0;
		}
		mMyGoalPole1 = new Vector(0, 0);
		mMyGoalPole2 = new Vector(0, 0);
		mOpGoalPole1 = new Vector(0, 0);
		mOpGoalPole2 = new Vector(0, 0);
		mMyCornerFlag1 = new Vector(0, 0);
		mMyCornerFlag2 = new Vector(0, 0);
		mOpCornerFlag1 = new Vector(0, 0);
		mOpCornerFlag2 = new Vector(0, 0);
	}

	public Vector ball() {
		return mBallPos;
	}

	public Vector myGoalPole1() {
		return mMyGoalPole1;
	}

	public Vector myGoalPole2() {
		return mMyGoalPole2;
	}

	public Vector opGoalPole1() {
		return mOpGoalPole1;
	}

	public Vector opGoalPole2() {
		return mOpGoalPole2;
	}

	public Vector myCornerFlag1() {
		return mMyCornerFlag1;
	}

	public Vector myCornerFlag2() {
		return mMyCornerFlag2;
	}

	public Vector opCornerFlag1() {
		return mOpCornerFlag1;
	}

	public Vector opCornerFlag2() {
		return mOpCornerFlag2;
	}

	public Vector teammate(int id) {
		if (id >= 0 && id < IClient.MAX_PLAYERS) {
			return mTeammatePos[id];
		} else {
			return me();
		}
	}

	public double teammateOrientation(int id) {
		if (id >= 0 && id < IClient.MAX_PLAYERS) {
			return mTeammateOrientation[id];
		} else {
			return 0;
		}		
	}

	public Vector opponent(int id) {
		if (id >= 0 && id < IClient.MAX_PLAYERS) {
			return mOpponentPos[id];
		} else {
			return me();
		}
	}

	public double opponentOrientation(int id) {
		if (id >= 0 && id < IClient.MAX_PLAYERS) {
			return mOpponentOrientation[id];
		} else {
			return 0;
		}		
	}

	public Vector me() {
		return new Vector(0, 0);
	}

	public Vector closestPlayer() {
		Vector me = new Vector(0, 0);
		Vector tm = teammate(closestTeammateTo(me));
		Vector op = opponent(closestOpponentTo(me));
		if (tm.getLength() < op.getLength()) {
			return tm;
		} else {
			return op;
		}
	}

	public int closestTeammateTo(Vector v) {
		double min = 9999999;
		int ret = -1;

		for (int i = 0; i < IClient.MAX_PLAYERS; i++) {
			Vector t = teammate(i).subtract(v);
			if (i != mClient.myID() && t.getLength() < min
					&& mClient.isTeammateFound(i)) {
				min = t.getLength();
				ret = i;
			}
		}
		return ret;
	}

	public int secondClosestTeammateTo(Vector v) {
		double min = 9999999;
		int temp = -1;
		int ret = -1;

		for (int i = 0; i < IClient.MAX_PLAYERS; i++) {
			Vector t = teammate(i).subtract(v);
			if (i != mClient.myID() && t.getLength() < min
					&& mClient.isTeammateFound(i)) {
				min = t.getLength();
				ret = temp;
				temp = i;
				
			}
		}
		return ret;
	}
	
	public int closestOfTeamTo(Vector v) {
		double min = 9999999;
		int ret = -1;

		for (int i = 0; i < IClient.MAX_PLAYERS; i++) {
			Vector t = teammate(i);
			Vector d = t.subtract(v);
			if (d.getLength() < min
					&& (mClient.isTeammateFound(i) || mClient.myID() == i)) {
				min = d.getLength();
				ret = i;
			}
		}
		return ret;
	}

	public int closestOpponentTo(Vector v) {
		double min = 9999999;
		int ret = -1;

		for (int i = 0; i < IClient.MAX_PLAYERS; i++) {
			Vector t = opponent(i).subtract(v);
			if (t.getLength() < min && mClient.isOpponentFound(i)) {
				min = t.getLength();
				ret = i;
			}
		}
		return ret;
	}

	public int closestTeammateToOpponent(int id) {
		return closestTeammateTo(opponent(id));
	}

	public int closestTeammateToTeammate(int id) {
		return closestTeammateTo(teammate(id));
	}

	public int closestOpponentToTeammate(int id) {
		return closestOpponentTo(teammate(id));
	}

	public int closestOpponentToOpponent(int id) {
		return closestOpponentTo(opponent(id));
	}

	public int closestTeammateToBall() {
		return closestTeammateTo(ball());
	}

	public int closestOpponentToBall() {
		return closestOpponentTo(ball());
	}

	public Vector getVectorByID(int vectorID) {
		switch (vectorID) {
			case 0:
				return new Vector(mBallPos, "ball");
			case 1:
				return new Vector(mMyGoalPole1, "myGoalPole1");
			case 2:
				return new Vector(mMyGoalPole2, "myGoalPole2");
			case 3:
				return new Vector(mOpGoalPole1, "opGoalPole1");
			case 4:
				return new Vector(mOpGoalPole2, "opGoalPole2");
			case 5:
				return new Vector(mMyCornerFlag1, "myCornerFlag1");
			case 6:
				return new Vector(mMyCornerFlag2, "myCornerFlag2");
			case 7:
				return new Vector(mOpCornerFlag1, "opCornerFlag1");
			case 8:
				return new Vector(mOpCornerFlag2, "opCornerFlag2");
			default:
				if (vectorID >= 9) {
					if (vectorID >= 9 + IClient.MAX_PLAYERS) {
						if (vectorID < 9 + (IClient.MAX_PLAYERS * 2)) {
							int player = vectorID - 13;
							return new Vector(opponent(player), "opponent" + player);
						} else {
							return null; // new Vector(0, 0, "Invalid ID");
						}
					} else {
						int player = vectorID - 9;
						return new Vector(teammate(player), "teammate" + player);
					}
				} else {
					return new Vector(0, 0, "Invalid ID");
				}
		}
	}

	public void setVectorByName(String name, Vector vector) {
		if (name.equals("ball")) {
			mBallPos = vector;
		} else if (name.equals("myGoalPole1")) {
			mMyGoalPole1 = vector;
		} else if (name.equals("myGoalPole2")) {
			mMyGoalPole2 = vector;
		} else if (name.equals("opGoalPole1")) {
			mOpGoalPole1 = vector;
		} else if (name.equals("opGoalPole2")) {
			mOpGoalPole2 = vector;
		} else if (name.equals("myCornerFlag1")) {
			mMyCornerFlag1 = vector;
		} else if (name.equals("myCornerFlag2")) {
			mMyCornerFlag2 = vector;
		} else if (name.equals("opCornerFlag1")) {
			mOpCornerFlag1 = vector;
		} else if (name.equals("opCornerFlag2")) {
			mOpCornerFlag2 = vector;
		} else {
			if (name.length() >= 8) {
				String team = name.substring(0, 8);
				int id = Integer.parseInt(name.substring(8));
				if (id >= 0 && id < IClient.MAX_PLAYERS) {
					if (team.equals("teammate")) {
						mTeammatePos[id] = vector;
					} else if (team.equals("opponent")) {
						mOpponentPos[id] = vector;
					}
				}
			}
		}
	}

	public void setBallPos(Vector ballPos) {
		mBallPos = ballPos;
	}

	public void setOpponentPos(int id, Vector opponentPos, double orientation) {
		mOpponentPos[id] = opponentPos;
		mOpponentOrientation[id] = orientation;
	}

	public void setTeammatePos(int id, Vector teammatePos, double orientation) {
		mTeammatePos[id] = teammatePos;
		mTeammateOrientation[id] = orientation;
	}

	public void setMyCornerFlag1(Vector myCornerFlag1) {
		mMyCornerFlag1 = myCornerFlag1;
	}

	public void setMyCornerFlag2(Vector myCornerFlag2) {
		mMyCornerFlag2 = myCornerFlag2;
	}

	public void setMyGoalPole1(Vector myGoalPole1) {
		mMyGoalPole1 = myGoalPole1;
	}

	public void setMyGoalPole2(Vector myGoalPole2) {
		mMyGoalPole2 = myGoalPole2;
	}

	public void setOpCornerFlag1(Vector opCornerFlag1) {
		mOpCornerFlag1 = opCornerFlag1;
	}

	public void setOpCornerFlag2(Vector opCornerFlag2) {
		mOpCornerFlag2 = opCornerFlag2;
	}

	public void setOpGoalPole1(Vector opGoalPole1) {
		mOpGoalPole1 = opGoalPole1;
	}

	public void setOpGoalPole2(Vector opGoalPole2) {
		mOpGoalPole2 = opGoalPole2;
	}
}